iT邦幫忙

2024 iThome 鐵人賽

DAY 5
0
JavaScript

TypeScript Type Challenges 冒險篇章:30 天闖關之旅,type 簡單了?你確定?系列 第 5

第5關:Tuple to Object!TypeScript 魔法現眼前:元組變物件

  • 分享至 

  • xImage
  •  

第5關:Tuple to Object

關卡簡介

Given an array, transform it into an object type and the key/value must be in the provided array.

給定一個陣列,將其轉換為物件型別,並且鍵和值必須來自所提供的陣列。

任務說明:

const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const

type result = TupleToObject<typeof tuple> 
// expected { 'tesla': 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}

接下來,你的任務是讓下面的type cases測試通過:

const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
const tupleNumber = [1, 2, 3, 4] as const
const sym1 = Symbol(1)
const sym2 = Symbol(2)
const tupleSymbol = [sym1, sym2] as const
const tupleMix = [1, '2', 3, '4', sym1] as const

type cases = [
  Expect<Equal<TupleToObject<typeof tuple>, { 'tesla': 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y' }>>,
  Expect<Equal<TupleToObject<typeof tupleNumber>, { 1: 1, 2: 2, 3: 3, 4: 4 }>>,
  Expect<Equal<TupleToObject<typeof tupleSymbol>, { [sym1]: typeof sym1, [sym2]: typeof sym2 }>>,
  Expect<Equal<TupleToObject<typeof tupleMix>, { 1: 1, '2': '2', 3: 3, '4': '4', [sym1]: typeof sym1 }>>,
]

冒險指南:

在這一關中,我們可以從以下幾個方向來思考:

  1. 什麼是 Tuple (元組)?
  2. Tuple 中的每個元素如何轉換成物件的鍵和值?
  3. 怎麼處理不同類型的 Tuple 元素,比如 string、number 或 symbol?

我們將會用到:

  1. Mapped Types:用來遍歷元組,並將其每個元素轉換為物件的鍵和值。我們會將元組的每一項元素映射為物件的屬性。
  2. Indexing Types:透過 T[number] 提取元組中的每個元素,將其作為物件的鍵和值。這個語法是用來遍歷數組或元組中的每個元素,並取回其型別。
  3. PropertyKey : TypeScript 內建型別,包含 stringnumbersymbol,表示物件屬性鍵的有效類型。這將幫助我們確保生成的物件鍵符合 TypeScript 規定的鍵類型。
Mapped Types 在第三關已經介紹過,可以回到第三關參考喔!

通關方式:

這次的挑戰可以透過一個簡單的 Mapped Types 來解決,我們會將 Tuple 的每個元素映射為物件中的鍵和值。

type TupleToObject<T extends readonly PropertyKey[]> = {
  [P in T[number]]: P
};

細節分析:

  • T extends readonly PropertyKey[]:限制 T 必須是 readonly PropertyKey[] 類型,即一個readonly的屬性鍵類型的元組。

  • [P in T[number]]: 這部分是映射類型的語法,用來遍歷元組 T 中的每個元素。T[number] 會提取出元組中的每個元素的聯合類型。

  • [P in T[number]]: P :定義了物件中的每一個屬性。對於 T 中的每一個元素 P,生成一個鍵為 P 的屬性,該屬性的值也為 P

這樣,我們就能順利通過測試啦 🎉 😭 🎉

關鍵字補給:

  • Tuple (元組):

    • 定義:
      • Tuple types allow you to express an array with a fixed number of elements whose types are known, but need not be the same.
      • A tuple in TypeScript is an array with a fixed number of elements.
      • Each element in the tuple can have a different type.
      • Tuples are often used when you know the exact number of elements and their types in advance.
      • Tuples can be mutable or immutable (readonly).
    • 範例:
      Example: Tuple
      // Declare a tuple type
      let x: [string, number];
      
      // Initialize it
      x = ["hello", 10]; // OK
      
      // Initialize it incorrectly
      x = [10, "hello"]; // Error
          // ^? Type 'number' is not assignable to type 'string'.
          // 	  Type 'string' is not assignable to type 'number'.
      
      Example: Mutable Tuple
      let tuple: [string, number, boolean];
      tuple = ["Hello", 42, true];
      
      tuple[0] = "World"; // This is allowed
      tuple[1] = 10; // This is allowed
      
      Example: Readonly Tuple
      let readonlyTuple: readonly [string, number, boolean];
      readonlyTuple = ["Hello", 42, true];
      
      // readonlyTuple[0] = "World"; // This will cause an error
      // readonlyTuple[1] = 10; // This will cause an error
      
  • const assertion (as const):

    • 用途:
      A construct for literal values called *const* assertions.
      Its syntax is a type assertion with const in place of the type name (e.g. 123 as const). When we construct new literal expressions with const assertions, we can signal to the language that
      • no literal types in that expression should be widened (e.g. no going from "hello" to string)
      • object literals get readonly properties
      • array literals become readonly tuples
    • 範例:
      // Type '"hello"'
      let x = "hello" as const;
      
      // Type 'readonly [10, 20]'
      let y = [10, 20] as const;
      
      // Type '{ readonly text: "hello" }'
      let z = { text: "hello" } as const;
      
  • T[number]:

    • 用途: In TypeScript, T[number] is a type that represents the union of all the types of the elements in the array (or tuple) T.

      • Indexed Access Type: T[number] is an example of an indexed access type. When you have an array or tuple type T, using T[number] means you are accessing the type of any element within that array or tuple.
      • Union of Element Types: The result is a union of the types of all elements in the array or tuple.
    • 範例:

      const tuple = ['apple', 'banana', 'cherry'] as const;
      type Tuple = typeof tuple; // ['apple', 'banana', 'cherry']
      type ElementType = Tuple[number]; // 'apple' | 'banana' | 'cherry'
      

總結:

本次介紹了 Tuple to Object 的實作,下一關會挑戰First of Array,期待再相見!


上一篇
第4關:Readonly!TypeScript 可遠觀不可褻玩焉: Readonly 保護罩
下一篇
第6關:First of Array!TypeScript 高要承認,挨打站穩:找出第一個元素
系列文
TypeScript Type Challenges 冒險篇章:30 天闖關之旅,type 簡單了?你確定?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言